##
# Tile
#
# Description: A tile on the map
#
##


class Tile:

    def __init__(self, position):

        # The x,y coordinates of this tile
        self.position = position

        # List of teams which have explored this tile
        self.explored = {}

        # an array of all the nodes that can be reached from this node
        self.neighbors = {}

        # The items on the tile
        self.stack = []

        # The tile keeps track of which items on the stack block sight and movement
        self.stackMoveBlockers = []
        self.stackSightBlockers = []

        return

    ##
    # exploreTile
    #
    # Description: marks that a team has explored the tile
    #
    # Parameters:
    #   Team - the team which is exploring the tile
    ##
    def exploreTile(self, Team):
        self.explored[Team] = True

    ##
    # addEntity
    #
    # Description: Add an entity to the tile
    #
    # Parameters:
    #   stackPosition - Order that things are stacked, 0 is lowest to the ground.
    #       Use negative numbers to add relative to the top where -1 would be add to the top
    #   newEntity - the object to add to the stack
    #
    def addEntity(self, newEntity, stackPosition=-1, touchStack=True):
        if touchStack:
            self.touchStack(newEntity)

        if newEntity.blocksMovement:
            self.stackMoveBlockers.append(newEntity)
        if newEntity.blocksVision:
            self.stackSightBlockers.append(newEntity)


        insertPos = self._getInsertPosition(stackPosition)
        self.stack.insert(insertPos, newEntity)

    ##
    # removeEntity
    #
    # Description: removes an entity from the stack
    #
    # Parameters:
    #   entityToRemove - the entity to remove
    def removeEntity(self, entityToRemove):

        if entityToRemove.blocksMovement:
            self.stackMoveBlockers.remove(entityToRemove)
        if entityToRemove.blocksVision:
            self.stackSightBlockers.remove(entityToRemove)

        while self.stack.count(entityToRemove) > 0:
            self.stack.remove(entityToRemove)

    ##
    # _getInsertPosition
    #
    # Description: gets the index to insert the a new entity into the stack with.
    #   Follows These Rules:
    #   0 is lowest to the ground.
    #   Negative Numbers to add relative to the top. (-1 adds to the top)
    #
    # Parameters:
    #   stackPosition - the desired position in the stack
    #
    # Returns: the index position to be used with stack.insert
    def _getInsertPosition(self, stackPosition):
        insertPos = stackPosition
        if stackPosition < 0:
            insertPos = len(self.stack) + stackPosition + 1

            # if still negative after adding the length then place it close to the ground
            if insertPos < 0:
                insertPos = 0

        return insertPos

    ##
    # touchStack
    #
    # Description: Calls on_touch on all entities in the stack using the same arguments as this function
    #
    # Parameters:
    #   toucher - the entity which touched the others
    ##
    def touchStack(self, toucher):

        for touched in self.stack:
            if hasattr(touched, "onTouch"):
                touched.onTouch(toucher)

        return

    ##
    # isMovementBlocking
    #
    # Description: Indicates weather or not an entity can move on top of by another object
    #
    # Returns: weather or not an entity can move on the tile
    ##
    def isMovementBlocking(self):
        return len(self.stackMoveBlockers) > 0

    ##
    # isSightBlocking
    #
    # Description: Indicates weather or not an entity can move on top of by another object
    #
    # Returns: weather or not an entity can move on the tile
    ##
    def isSightBlocking(self):
        return len(self.stackSightBlockers) > 0